﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using Akiha.Core;
using ESRI.ArcGIS.Geometry;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraTreeList.Nodes;
using System.Windows.Forms;
using DevExpress.XtraTreeList;

namespace ArcMap_AddIn_Tools.AppDialog.DataChecker
{
    //AO数据检查类
    //包括图形数据和属性数据的检查
    //真正做到功能与界面分离
    //如果单独的检查代码量比较大可以单独拆分成类去实现
    //这里的都是相对简单的检查因此整合成一个类即可
    

    //属性检查的枚举类型
    public enum PropertyCheckType
    {
        是否为空=0,
        唯一值检测=1,
        长度检查=2,
        复合逻辑检查=3
    }






    public class DataCheckerForAO
    {

        //待检查的数据
        private List<IFeature> m_lstFeas = null;

        //private 

        //保存检查结果
        //保存的形式Table,dic,List
        //保存属性值检查结果
        //以多级Dic的形式保存检查结果，通用的写法
        //可考虑复写TreeNode来实现多级dic
        private Dictionary<IFeatureLayer, Dictionary<PropertyCheckType, Dictionary<string, List<IFeature>>>> m_dicPropertyCheckResult = new Dictionary<IFeatureLayer, Dictionary<PropertyCheckType, Dictionary<string, List<IFeature>>>>();




        //构造函数
        public DataCheckerForAO()
        {
            
           
            
        }


        //属性值检查
        //通过配置文件来进行检查
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt">检查配置的数据集，按图层名区分有若干个table</param>
        /// <param name="pMap"></param>
        public Dictionary<IFeatureLayer, Dictionary<PropertyCheckType, Dictionary<string, List<IFeature>>>> PropertyValueCheck(DataSet ds, IMap pMap)
        {
            List<IFeatureLayer> lstFeaLyr = MapWrapper.GetLayers(pMap, null);
            //m_GridControl
            
            

            //保存要素类的检查结果
            //键字段信息
            //值检查类型
            foreach (IFeatureLayer feaLyr in lstFeaLyr)
            {               
                DataTable dt = ds.Tables[feaLyr.Name];
                if (dt==null||dt.Rows.Count==0)
                {
                    continue;
                }
                Dictionary<PropertyCheckType, Dictionary<string, List<IFeature>>> keyvalueCheckType = new Dictionary<PropertyCheckType, Dictionary<string, List<IFeature>>>();
                List<IFeature> lstFeas = FeatureClassWrapper.GetFeaturesFromFeatureClass(feaLyr.FeatureClass, null);
                
                //保存空值类型的字典
                Dictionary<string, List<IFeature>> dicIsNull=new Dictionary<string,List<IFeature>>();
                Dictionary<string, List<IFeature>> dicIsUnique=new Dictionary<string,List<IFeature>>();
                Dictionary<string, List<IFeature>> dicCheckLength=new Dictionary<string,List<IFeature>>();


                //一个项目一个项目检查
                foreach (DataRow item  in dt.Rows)
                {
                    if ((bool)(item["打开"]) == true)
                    {
                        string checkType = item["检查类别"].ToString();
                        string strFieldName = item["属性名称"].ToString();                      
                        string strFieldName_CN = item["检查属性"].ToString();
                        if (checkType == PropertyCheckType.是否为空.ToString())
                        {
                            List<IFeature> lst = PropertyValueCheckerWrapper.checkIsNull(lstFeas, strFieldName);
                            if (lst==null||lst.Count==0)
                            {
                                continue;
                            }
                            dicIsNull.Add(strFieldName_CN, lst);
                        }
                        else if (checkType == "唯一值检测")
                        {
                            List<IFeature> lst = PropertyValueCheckerWrapper.checkIsUnique(lstFeas, strFieldName);
                            dicIsUnique.Add(strFieldName_CN, lst);
                        }
                        else if (checkType == "长度检查")
                        {
                            List<IFeature> list = null;
                            if (strFieldName == "ZDH")//7
                            {
                                list = PropertyValueCheckerWrapper.checkLength(lstFeas, strFieldName, 7);
                                dicCheckLength.Add(strFieldName_CN, list);
                            }
                            else if (strFieldName == "DJH")//19
                            {
                                list = PropertyValueCheckerWrapper.checkLength(lstFeas, strFieldName, 19);
                                dicCheckLength.Add(strFieldName_CN, list);
                            }
                        }
                    }
                }


                keyvalueCheckType.Add(PropertyCheckType.是否为空, dicIsNull);
                keyvalueCheckType.Add(PropertyCheckType.唯一值检测, dicIsUnique);
                keyvalueCheckType.Add(PropertyCheckType.长度检查, dicCheckLength);

                m_dicPropertyCheckResult.Add(feaLyr, keyvalueCheckType);

            }
            return m_dicPropertyCheckResult;
                        
        }



        //重载的属性值检查
        //用于手动指定检查规则
        //待定
        public void ProertValueCheck()
        {

        }

        

        //字段检查
        public void FieldsCheck()
        {

        }

        //拓扑检查

        public void TopologyCheck()
        {

        }

        //图形检查
        //如微小面检查
        public void GraphCheck()
        {

        }


    }

    //属性检查方法类
    //这个需要融入上面的类中
    //或者是单独的Wrapper保存在Core中
    //这里为求简便融入上面的类中
    public static class PropertyValueCheckerWrapper
    {
        //检查字段为空的项
        //包括null和空字符串
        //传入字段的名称，非别名
        public static List<IFeature> checkIsNull(List<IFeature> lstFeas, string strField)
        {
            //传入null或者空集合返回null
            if (lstFeas == null || lstFeas.Count == 0) return null;

            List<IFeature> list = new List<IFeature>();//objectid,属性名

            int index = lstFeas[0].Fields.FindField(strField);
            if (index != -1)
            {
                //判断是否为空
                foreach (IFeature pFea in lstFeas)
                {
                    //getvalue始终不会返回null对于unllable返回的是DBNull.value
                    if (string.IsNullOrEmpty(pFea.get_Value(index).ToString()))
                    {
                        //String[] str = new String[] { pFeature.get_Value(0).ToString(), fieldName[1] };
                        list.Add(pFea);
                    }
                }

            }
            else { return null; }

            return list;
        }


        //查询唯一值的情况
        //通用于各种类型的数据，不仅支持字符串还支持数值类型
        //原则上将上一个相同的字段也包含进来
        //这种情况下也可能将DBNull和空值的情况查询出来，因此要对此种情况进行过滤
        public static List<IFeature> checkIsUnique(List<IFeature> lstFeas, String fieldName)
        {
            if (lstFeas == null || lstFeas.Count == 0) return null;

            List<IFeature> list = new List<IFeature>();//objectid,属性名
            Dictionary<string, IFeature> keyvalue = new Dictionary<string, IFeature>();

            int index = lstFeas[0].Fields.FindField(fieldName);

            if (index != -1)
            {
                foreach (IFeature pFea in lstFeas)
                {

                    if (string.IsNullOrEmpty(pFea.get_Value(index).ToString()))
                    {
                        continue;
                    }

                    if (keyvalue.ContainsKey(pFea.get_Value(index).ToString()))
                    {
                        // String[] str = new String[] { pFeature.get_Value(0).ToString(), fieldName[1] };
                        list.Add(pFea);
                        //同时保存与原先相同的fea，并且过滤掉相同的引用
                        IFeature pTmpFea = keyvalue[pFea.get_Value(index).ToString()];
                        if (!list.Contains(pTmpFea))
                        {
                            list.Add(pTmpFea);
                        }
                    }
                    else
                    {
                        keyvalue.Add(pFea.get_Value(index).ToString(), pFea);
                    }

                }
            }

            return list;
        }



        //检查字段长度，这里暂且没考虑其它类型字段，最好传递字符串类型数据
        public static List<IFeature> checkLength(List<IFeature> lstFeas, String fieldName, int length)
        {
            if (lstFeas == null || lstFeas.Count == 0) return null;
            List<IFeature> list = new List<IFeature>();


            int index = lstFeas[0].Fields.FindField(fieldName);
            if (index != -1)
            {
                foreach (IFeature pFea in lstFeas)
                {
                    String value = pFea.get_Value(index).ToString();
                    if (value.Length != length)
                    {
                        //String[] str = new String[] { pFeature.get_Value(0).ToString(), fieldName[1], length.ToString() };
                        list.Add(pFea);
                    }
                }
            }
            return list;
        }
    }





}
